using System;
using System.Collections;
using System.Collections.Generic;

namespace System.Collections
{
    /// <summary>
    /// A Queue<> implementation wrapper, which implements IQueue<>
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public sealed class GenericQueue<T> : IQueue<T>
    {
        #region Private Variables
        private System.Collections.Generic.Queue<T> _RealQueue;
        #endregion

        #region Constructors
        public GenericQueue()
            : this(new System.Collections.Generic.Queue<T>())
        {
        }

        public GenericQueue(System.Collections.Generic.Queue<T> realQueue)
        {
            if (realQueue == null)
                throw new ArgumentNullException("realQueue");
            this._RealQueue = realQueue;
        }

        public GenericQueue(T[] initialContents)
            :this(new System.Collections.Generic.Queue<T>(initialContents))
        {
        }

        public GenericQueue(int capacity)
            :this(new System.Collections.Generic.Queue<T>(capacity))
        {
        }
        #endregion

        #region IQueue<T> Members

        public T Peek()
        {
            return _RealQueue.Peek();
        }

        public void Enqueue(T value)
        {
            _RealQueue.Enqueue(value);
        }

        public T Dequeue()
        {
            return _RealQueue.Dequeue();
        }

        public T[] Dequeue(int count)
        {
            System.Collections.Generic.List<T> tl = new System.Collections.Generic.List<T>();
            int xm = this.Count;
            int x = 0;
            for (x = 0; (x < count) && (x < xm); x++)
            {
                tl.Add(this.Dequeue());
            }
            return tl.ToArray();
        }
        object[] IQueue.Dequeue(int count)
        {
            System.Collections.Generic.List<object> tl = new System.Collections.Generic.List<object>();
            int xm = this.Count;
            int x = 0;
            for (x = 0; (x < count) && (x < xm); x++)
            {
                tl.Add((object)this.Dequeue());
            }
            return tl.ToArray();
        }

        public bool Contains(T value)
        {
            return _RealQueue.Contains(value);
        }

        #endregion

        #region IQueue Members

        object IQueue.Peek()
        {
            return this.Peek();
        }

        void IQueue.Enqueue(object value)
        {
            this.Enqueue((T)value);
        }

        object IQueue.Dequeue()
        {
            object v;
            v = _RealQueue.Dequeue();
            return v;
        }

        public bool Contains(object value)
        {
            return this.Contains((T)value);
        }

        public void Clear()
        {
            _RealQueue.Clear();
        }

        #endregion

        #region ICollection Members

        public void CopyTo(Array array, int index)
        {
            ((ICollection)_RealQueue).CopyTo(array, index);
        }

        public int Count
        {
            get { return _RealQueue.Count; }
        }

        public bool IsSynchronized
        {
            get { return ((ICollection)_RealQueue).IsSynchronized; }
        }

        public object SyncRoot
        {
            get { return ((ICollection)_RealQueue).SyncRoot; }
        }

        #endregion

        #region IEnumerable Members

        public IEnumerator GetEnumerator()
        {
            return _RealQueue.GetEnumerator();
        }

        #endregion

        #region IQueue Members


        public void Enqueue(object value)
        {
            _RealQueue.Enqueue((T)value);
        }

        #endregion

        #region IQueue<T> Members


        public T[] Peek(int count)
        {
            List<T> lResult = new List<T>();
            lResult.AddRange(this.ToArray());
            if(lResult.Count > count)
            {
                lResult.RemoveRange(count, lResult.Count - count);
            }
            return lResult.ToArray();
        }

        public T[] ToArray()
        {
            return _RealQueue.ToArray();
        }

        #endregion

        #region IQueue Members


        object[] IQueue.Peek(int count)
        {
            List<object> lResult = new List<object>();
            lResult.AddRange((object[])((Array)this.ToArray()));
            if (lResult.Count > count)
            {
                lResult.RemoveRange(count, lResult.Count - count);
            }
            return lResult.ToArray();
        }

        object[] IQueue.ToArray()
        {
            List<object> lResult = new List<object>();
            lResult.AddRange((object[])((Array)this.ToArray()));
            return lResult.ToArray();
        }

        #endregion

        #region IQueue<T> Members


        public void Enqueue(T[] values)
        {
            foreach (T v in values)
            {
                this.Enqueue(v);
            }
        }

        #endregion

        #region IQueue Members


        public void Enqueue(object[] values)
        {
            foreach (object v in values)
            {
                this.Enqueue(v);
            }
        }

        #endregion
    }
}
